from __future__ import absolute_import
import logging
from os.path import exists

from forest.api import Command, get_tool


logger = logging.getLogger('forest.commands.Cleanup')

class Cleanup(Command):
    ''' any cleanup procedure after install. currently, unmount,
    and a check for broken hard links.
    '''
    __register__ = 'commands.install.Cleanup'

    def run(self, config):

        install_root = config.get_install_root()
        with get_tool('system.chroot')(install_root):
            for broken in self.find_broken_files('type f -links +1'): # self.find_broken_links():
                get_tool('system.remove')(broken)

        for mountpoint in config.get('_mounted', []):
            get_tool('system.unmount')(mountpoint, lazy=True)
        #get_tool('system.unmount')(install_root, lazy=True)

        # TODO: extlinux sets the unmodifyable attribute
        # chattr -i extlinux.sys
        # to remove the files from {ext,sys}linux --install

    @staticmethod
    def find_broken_links():
        '''Finds broken symbolic or hard links, checking all files with
        multiple names to an inode for the latter.'''
        for res in Cleanup.find_broken_files('type f -links +1'):
            yield res
        for res in Cleanup.find_broken_files('type l'):
            yield res

    @staticmethod
    def find_broken_files(test, root = '/'):
        ''' Checks for non-existant files, filtered by some test
        '''

        excludes = ['dev', 'run', 'proc', 'sys']

        for err, out in get_tool('files.find')(root, tests=test):
            if err:
                continue
            filename = out.strip()
            path = filename.strip(root).split('/')
            try:
                #'proc/', './proc', '/proc' should all get found
                if path[0] in excludes or path[1] in excludes:
                    continue
            #ackward - when there is no '/' in path
            except IndexError:
                pass
            if exists(filename):
                continue
            yield filename
